package com.example.demo.http;


import org.apache.http.HttpHost;
import org.apache.http.config.ConnectionConfig;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.config.SocketConfig;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.TrustStrategy;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.ssl.SSLContexts;

import javax.net.ssl.SSLContext;
import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.concurrent.TimeUnit;

/**
 * 配置的一些连接池相关数据以及证书认证等
 * @author zyc
 */
public class HttpConnectionPoolManager {
    private static HttpConnectionPoolManager manager = new HttpConnectionPoolManager();
    private PoolingHttpClientConnectionManager cm;
    private PoolingHttpClientConnectionManager sslCm;
    /**
     * 整个连接池最大连接数
     */
    private int CONNECTION_POOL = 100;
    /**
     * 路由最大连接数，默认值是2,对于同一个目标机器的最大并发连接
     *
     */
    private int ROUTE_NUM = 1000;
    private HttpHost proxy;

    public HttpConnectionPoolManager() {
        super();
        init();
    }

    private void init() {
        // .loadKeyMaterial()加载客户端证书
        //加载服务端提供的truststore(如果服务器提供truststore的话就不用忽略对服务器端证书的校验了)
        //.loadTrustMaterial(new File("D:\\truststore.jks"), "123456".toCharArray(),
        //        new TrustSelfSignedStrategy())
        //  .loadKeyMaterial(keyStore, "cmcc".toCharArray())
        SSLContext sslcontext = null;
        //全部信任
        try {
            sslcontext = SSLContexts.custom().loadTrustMaterial(null, new TrustStrategy() {
                @Override
                public boolean isTrusted(X509Certificate[] chain, String authType) throws CertificateException {
                    return true;
                }
            }).build();
        } catch (NoSuchAlgorithmException | KeyManagementException | KeyStoreException e) {
            e.printStackTrace();
        }
        SSLConnectionSocketFactory sslConnectionSocketFactory = new SSLConnectionSocketFactory(
                sslcontext,
                new String[]{"SSLv2Hello", "SSLv3", "TLSv1", "TLSv1.2"},
                null,
                NoopHostnameVerifier.INSTANCE);
        Registry<ConnectionSocketFactory> registry = RegistryBuilder.<ConnectionSocketFactory>create()
                .register("http", new PlainConnectionSocketFactory())
                .register("https", sslConnectionSocketFactory)
                .build();
        cm = new PoolingHttpClientConnectionManager(registry);
        // 整个连接池最大连接数
        cm.setMaxTotal(CONNECTION_POOL);
        // 每路由最大连接数，默认值是2,对于同一个目标机器的最大并发连接
        cm.setDefaultMaxPerRoute(ROUTE_NUM);
        SocketConfig socketConfig = SocketConfig.custom().setSoKeepAlive(true).build();
        cm.setDefaultSocketConfig(socketConfig);
        //validateAfterInactivity 空闲永久连接检查间隔
        //官方推荐使用这个来检查永久链接的可用性，而不推荐每次请求的时候才去检查
        cm.setValidateAfterInactivity(2000);
        //连接配置
        ConnectionConfig connectionConfig = ConnectionConfig.DEFAULT;
        cm.setDefaultConnectionConfig(connectionConfig);
    }

    public static HttpConnectionPoolManager getInstance() {
        return manager;
    }

    public PoolingHttpClientConnectionManager getPoolingHttpClientConnectionManager() {
        return cm;
    }

    public void closeExpiredConnections() {
        cm.closeExpiredConnections();
    }

    public void closeIdleConnections(int seconds) {
        cm.closeIdleConnections(seconds, TimeUnit.SECONDS);
    }
}
